<template>
	<view class="scan-wrap">
		<view class="scan-container">
			<canvas :id="cid" :canvas-id="cid" ref="myCanvas" class="scan-canvas"></canvas>

			<view class="scan-overlay">
				<!-- Corner brackets -->
				<view class="corner tl"></view>
				<view class="corner tr"></view>
				<view class="corner bl"></view>
				<view class="corner br"></view>
				<!-- Scanning line -->
				<view class="scan-line" :style="{ top: scanLinePos + 'px' }"></view>
				<!-- Grid overlay -->
				<view class="grid-overlay"></view>
			</view>
		</view>
		<view class="row">
			<button size="mini" @tap="choose">选择图片</button>
			<button size="mini" @tap="startScan" :disabled="scanning">{{ scanning ? '扫描中...' : '开始扫描' }}</button>
			<button size="mini" @tap="stopScan" v-if="scanning">停止</button>
		</view>
		<view class="row">
			<button size="mini" @tap="testBasicDecode" :disabled="!tempPath">测试解码</button>
			<button size="mini" @tap="testRuleDecode" :disabled="!tempPath">规则解码</button>
		</view>
		<view class="processing-status">
			<text class="status-label">处理状态：</text>
			<text class="status-value" :class="processingStatus === '解码成功' ? 'success' : (processingStatus === '处理中...' ? 'processing' : 'warning')">{{ processingStatus }}</text>
		</view>
		<view class="decode-stats" v-if="decodeStats.attempts > 0">
			<text class="stats-label">解码统计：</text>
			<text class="stats-text">尝试: {{ decodeStats.attempts }} | 成功: {{ decodeStats.successes }} | 成功率: {{ Math.round(decodeStats.successes / decodeStats.attempts * 100) }}%</text>
			<text class="stats-text">平均时间: {{ Math.round(decodeStats.avgTime) }}ms | 上次: {{ decodeStats.lastDecodeTime }}ms</text>
		</view>
		<view class="result">{{ result || '结果会显示在这里' }}</view>
	</view>
</template>

<script>
import { decodeSunCodeStructuredWithReader, decodeSunCodeStructured, decodeSunCodeFromImageData, decodeSunCodeByRules } from '@/utils/suncode.js'

export default {
	name: 'SunScan',
		data() {
		return {
			cid: 'sun_scan_' + Math.random().toString(36).slice(2),
			cameraId: 'sun_camera_' + Math.random().toString(36).slice(2),
			tempPath: '',
			result: '',
			ctx:null,
			scanning: false,
			scanLinePos: 0,
			scanTimer: null,
			scanTimeoutTimer: null,
			scanStartTime: 0,
			maxScanMs: 8000,
			cameraMode: false,
			cameraContext: null,
			markers: [],
			detectedCenter: null,
			markerDetectionStatus: '未检测',
			decodeStats: {
				attempts: 0,
				successes: 0,
				avgTime: 0,
				lastDecodeTime: 0,
				bestScore: 0
			},
			processingStatus: '就绪',
			debugInfo: {
				markersDetected: 0,
				centerDetected: false,
				multiScaleResult: null,
				configsTried: 0,
				centersTried: 0
			}
		}
	},
	methods: {
		toggleMode() {
			this.stopScan()
			this.cameraMode = !this.cameraMode
			if (this.cameraMode) {
				this.initCamera()
			}
		},
		initCamera() {
			// Initialize camera context for capturing frames
			this.cameraContext = uni.createCameraContext(this.cameraId, this)
		},
		onCameraError(e) {
			console.error('Camera error:', e)
			uni.showToast({ title: '相机启动失败', icon: 'none' })
			this.cameraMode = false
		},
		choose() {
			var that = this;
			uni.chooseImage({ 
				count: 1,
				success: (res) => { 
					that.tempPath = res.tempFilePaths[0]; 
					console.log(that.tempPath)
					that.draw(); 
				} 
			})
		},
		draw() {
			if(this.tempPath.length == 0) return
			this.ctx = uni.createCanvasContext(this.cid,this);
			this.ctx.drawImage(this.tempPath,0,0,300,300);
			this.ctx.draw();
		},
		startScan() {
			// if (this.cameraMode) {
			// 	this.startCameraScan()
			// } else {
				if (!this.tempPath) { uni.showToast({ title: '请先选择图片', icon: 'none' }); return }
				this.startImageScan()
			// }
		},
		startImageScan() {
			this.scanning = true
			this.scanStartTime = Date.now()
			this.scanLinePos = 0
			this.scanTimer = setInterval(() => {
				this.scanLinePos += 2
				if (this.scanLinePos > 300) this.scanLinePos = 0
				this.decodeFromCanvas()
			}, 120)
			// 启动超时定时器
			if (this.scanTimeoutTimer) { clearTimeout(this.scanTimeoutTimer); this.scanTimeoutTimer = null }
			this.scanTimeoutTimer = setTimeout(() => {
				if (this.scanning) {
					this.processingStatus = '解码失败'
					this.stopScan()
					uni.showToast({ title: '扫码失败', icon: 'none' })
				}
			}, this.maxScanMs)
		},
		stopScan() {
			this.scanning = false
			if (this.scanTimer) { clearInterval(this.scanTimer); this.scanTimer = null }
			if (this.scanTimeoutTimer) { clearTimeout(this.scanTimeoutTimer); this.scanTimeoutTimer = null }
		},
		async decodeFromCanvas() {
			if (!this.ctx) return

			uni.canvasGetImageData({
				canvasId: this.cid,
				x: 0, y: 0, width: 300, height: 300,
				success: async (res) => {
					const data = res.data
					const width = 300, height = 300
					
					const startTime = Date.now()
					this.processingStatus = '处理中...'
					this.decodeStats.attempts++
					
					try {
						// 使用优化的结构化解码器
						const decoded = await decodeSunCodeFromImageData(data, width, height)
						
						const endTime = Date.now()
						const decodeTime = endTime - startTime
						
						// 更新统计信息
						this.decodeStats.lastDecodeTime = decodeTime
						this.decodeStats.avgTime = (this.decodeStats.avgTime * (this.decodeStats.attempts - 1) + decodeTime) / this.decodeStats.attempts
						
						if (decoded && decoded.trim()) {
							this.result = decoded
							this.decodeStats.successes++
							this.processingStatus = '解码成功'
							
							if (this.scanning) {
								this.stopScan()
								uni.showToast({ 
									title: `扫描成功 (${decodeTime}ms)`, 
									icon: 'success' 
								})
							}
						} else {
							this.processingStatus = '未检测到太阳码'
							console.log('解码失败，调试信息:', this.debugInfo)
						}
					} catch (e) {
						console.error('太阳码解码错误:', e)
						this.processingStatus = '解码失败'
						if (!this.scanning) this.result = e.message || '解码失败'
					}
				},
				fail: (e) => {
					console.error('getImageData fail', e)
					this.processingStatus = '获取图像失败'
				}
			}, this)
		},
		getCanvasElement() {
			return this.$refs.myCanvas;
		},
		// 测试基本解码功能
		async testBasicDecode() {
			if (!this.tempPath) {
				uni.showToast({ title: '请先选择图片', icon: 'none' });
				return;
			}
			
			try {
				this.processingStatus = '测试解码中...';
				
				// 直接使用原始图像数据测试
				uni.canvasGetImageData({
					canvasId: this.cid,
					x: 0, y: 0, width: 300, height: 300,
					success: async (res) => {
						const data = res.data;
						const width = 300, height = 300;
						
						// 测试不同的解码方法
						console.log('开始测试基本解码...');
						
						// 方法1：直接使用原始数据
						try {
							const result1 = await decodeSunCodeFromImageData(data, width, height);
							console.log('方法1结果:', result1);
							if (result1) {
								this.result = `方法1成功: ${result1}`;
								return;
							}
						} catch (e) {
							console.log('方法1失败:', e.message);
						}
						
						// 方法2：使用简化的解码
						try {
							const result2 = await this.simpleDecode(data, width, height);
							console.log('方法2结果:', result2);
							if (result2) {
								this.result = `方法2成功: ${result2}`;
								return;
							}
						} catch (e) {
							console.log('方法2失败:', e.message);
						}
						
						this.result = '所有方法都失败了';
						this.processingStatus = '测试完成';
					},
					fail: (e) => {
						console.error('获取图像数据失败:', e);
						this.processingStatus = '获取图像失败';
					}
				}, this);
			} catch (e) {
				console.error('测试解码错误:', e);
				this.processingStatus = '测试失败';
			}
		},
		// 简化的解码方法
		async simpleDecode(imageData, width, height) {
			const cx = width / 2;
			const cy = height / 2;
			const maxR = Math.min(width, height) / 2 * 0.8;
			
			// 尝试最简单的配置
			const config = { version: 1, rings: 6, sectors: (r) => 32 + 4 * r };
			
			// 简单的采样
			const matrix = [];
			const ringWidth = maxR / (config.rings + 1);
			
			for (let r = 0; r < config.rings; r++) {
				const S = config.sectors(r);
				const inner = ringWidth * (r + 1);
				const radius = inner + ringWidth * 0.5;
				const ringBits = [];
				
				for (let s = 0; s < S; s++) {
					const angle = (s + 0.5) / S * 2 * Math.PI;
					const x = Math.round(cx + radius * Math.cos(angle));
					const y = Math.round(cy + radius * Math.sin(angle));
					
					if (x < 0 || x >= width || y < 0 || y >= height) {
						ringBits.push(0);
						continue;
					}
					
					const idx = (y * width + x) * 4;
					const r_val = imageData[idx];
					const g_val = imageData[idx + 1];
					const b_val = imageData[idx + 2];
					const lum = 0.2126 * r_val + 0.7152 * g_val + 0.0722 * b_val;
					
					ringBits.push(lum < 128 ? 1 : 0);
				}
				
				matrix.push(ringBits);
			}
			
			// 尝试规则解码
			return decodeSunCodeByRules(matrix, config);
		},
		// 测试规则解码
		async testRuleDecode() {
			if (!this.tempPath) {
				uni.showToast({ title: '请先选择图片', icon: 'none' });
				return;
			}
			
			try {
				this.processingStatus = '规则解码测试中...';
				
				uni.canvasGetImageData({
					canvasId: this.cid,
					x: 0, y: 0, width: 300, height: 300,
					success: async (res) => {
						const data = res.data;
						const width = 300, height = 300;
						
						console.log('开始规则解码测试...');
						
						// 测试不同版本
						const versions = [1, 2, 3, 4, 5];
						let bestResult = '';
						let bestScore = 0;
						
						for (const version of versions) {
							const config = { 
								version, 
								rings: 6 + 2 * (version - 1), 
								sectors: (r) => 32 + 4 * r 
							};
							
							console.log(`测试版本 ${version}...`);
							
							// 采样矩阵
							const matrix = await this.sampleMatrixForVersion(data, width, height, config);
							
							// 规则解码
							const result = decodeSunCodeByRules(matrix, config);
							
							if (result && result.length > 0) {
								const score = result.length;
								console.log(`版本 ${version} 解码成功:`, result, '得分:', score);
								
								if (score > bestScore) {
									bestScore = score;
									bestResult = result;
								}
							} else {
								console.log(`版本 ${version} 解码失败`);
							}
						}
						
						if (bestResult) {
							this.result = `规则解码成功: ${bestResult}`;
							this.processingStatus = '规则解码成功';
						} else {
							this.result = '规则解码失败';
							this.processingStatus = '规则解码失败';
						}
					},
					fail: (e) => {
						console.error('获取图像数据失败:', e);
						this.processingStatus = '获取图像失败';
					}
				}, this);
			} catch (e) {
				console.error('规则解码测试错误:', e);
				this.processingStatus = '测试失败';
			}
		},
		// 为特定版本采样矩阵
		async sampleMatrixForVersion(imageData, width, height, config) {
			const cx = width / 2;
			const cy = height / 2;
			const maxR = Math.min(width, height) / 2 * 0.8;
			const ringWidth = maxR / (config.rings + 1);
			const matrix = [];
			
			for (let r = 0; r < config.rings; r++) {
				const S = config.sectors(r);
				const inner = ringWidth * (r + 1);
				const radius = inner + ringWidth * 0.5;
				const ringBits = [];
				
				for (let s = 0; s < S; s++) {
					const angle = (s + 0.5) / S * 2 * Math.PI;
					const x = Math.round(cx + radius * Math.cos(angle));
					const y = Math.round(cy + radius * Math.sin(angle));
					
					if (x < 0 || x >= width || y < 0 || y >= height) {
						ringBits.push(0);
						continue;
					}
					
					const idx = (y * width + x) * 4;
					const r_val = imageData[idx];
					const g_val = imageData[idx + 1];
					const b_val = imageData[idx + 2];
					const lum = 0.2126 * r_val + 0.7152 * g_val + 0.0722 * b_val;
					
					ringBits.push(lum < 128 ? 1 : 0);
				}
				
				matrix.push(ringBits);
			}
			
			return matrix;
		}
	},
	beforeDestroy() {
		this.stopScan()
	}
}
</script>

<style scoped>
.scan-wrap {
	padding: 12px;
}

.scan-container {
	position: relative;
	display: inline-block;
}

.scan-canvas {
	width: 300px;
	height: 300px;
	background: #f7f7f7;
	border-radius: 8px;
}

.camera-preview {
	width: 300px;
	height: 300px;
	border-radius: 8px;
}

.scan-overlay {
	position: absolute;
	top: 0;
	left: 0;
	width: 300px;
	height: 300px;
	pointer-events: none;
}

.corner {
	position: absolute;
	width: 20px;
	height: 20px;
	border: 3px solid #00ff00;
}

.corner.tl {
	top: 20px;
	left: 20px;
	border-right: none;
	border-bottom: none;
}

.corner.tr {
	top: 20px;
	right: 20px;
	border-left: none;
	border-bottom: none;
}

.corner.bl {
	bottom: 20px;
	left: 20px;
	border-right: none;
	border-top: none;
}

.corner.br {
	bottom: 20px;
	right: 20px;
	border-left: none;
	border-top: none;
}

.scan-line {
	position: absolute;
	left: 20px;
	right: 20px;
	height: 2px;
	background: linear-gradient(90deg, transparent, #00ff00, transparent);
	animation: scan-pulse 1s ease-in-out infinite;
}

.grid-overlay {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-image: linear-gradient(rgba(0, 255, 0, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 255, 0, 0.1) 1px, transparent 1px);
	background-size: 20px 20px;
}

.row {
	display: flex;
	gap: 8px;
	margin-top: 8px;
}

/* 去除基准点相关样式 */

.processing-status {
	margin-top: 8px;
	padding: 6px 8px;
	background: #f0f8ff;
	border-radius: 4px;
	font-size: 12px;
}

.processing-status .status-value.processing {
	color: #1890ff;
	animation: pulse 1s infinite;
}

.decode-stats {
	margin-top: 8px;
	padding: 8px;
	background: #f8f9fa;
	border-radius: 4px;
	font-size: 11px;
}

.stats-label {
	display: block;
	font-weight: bold;
	color: #333;
	margin-bottom: 4px;
}

.stats-text {
	display: block;
	color: #666;
	line-height: 1.3;
}

.debug-info {
	margin-top: 8px;
	padding: 8px;
	background: #fff3cd;
	border-radius: 4px;
	font-size: 11px;
	border-left: 4px solid #ffc107;
}

.debug-label {
	display: block;
	font-weight: bold;
	color: #856404;
	margin-bottom: 4px;
}

.debug-text {
	display: block;
	color: #856404;
	line-height: 1.3;
}

.result {
	margin-top: 6px;
	color: #666;
	font-size: 12px;
	word-break: break-all;
}

@keyframes pulse {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.5; }
}

@keyframes scan-pulse {

	0%,
	100% {
		opacity: 0.3;
	}

	50% {
		opacity: 1;
	}
}
</style>
